---
title: TanStack Start
icon: TreePalm
---
import { Step, Steps } from "fumadocs-ui/components/steps";

This guide covers integrating `@daveyplate/better-auth-ui` v3 with TanStack Start. We also install [@daveyplate/better-auth-tanstack](https://github.com/daveyplate/better-auth-tanstack) to handle the authentication state and queries.

## Starter Project

Want to skip the installation? Check out the starter here:

[GitHub](https://github.com/daveyplate/better-auth-tanstack-starter) - [Demo](https://tanstack.better-auth-starter.com)

## Installation

<Steps>
<Step>
### Set up the Auth Provider

TanStack Start requires setting up providers slightly differently than a standard React application. Create a root-level provider component:

```tsx title="app/providers.tsx"
import { AuthQueryProvider } from "@daveyplate/better-auth-tanstack"
import { AuthUIProviderTanstack } from "@daveyplate/better-auth-ui/tanstack"
import { Link, useRouter } from "@tanstack/react-router"
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
import type { ReactNode } from "react"

import { authClient } from "./lib/auth-client"

// Create a client
const queryClient = new QueryClient({
    defaultOptions: {
        queries: {
            staleTime: 1000 * 60
        }
    }
})

export function Providers({ children }: { children: ReactNode }) {
    const router = useRouter()
    
    return (
        <QueryClientProvider client={queryClient}>
            <AuthQueryProvider>
                <AuthUIProviderTanstack
                    authClient={authClient}
                    navigate={(href) => router.navigate({ href })}
                    replace={(href) => router.navigate({ href, replace: true })}
                    Link={({ href, ...props }) => <Link to={href} {...props} />}
                >
                    {children}
                </AuthUIProviderTanstack>
            </AuthQueryProvider>
        </QueryClientProvider>
    )
}
```

Note how we use TanStack Router's `useRouter` hook and `Link` component to handle navigation.
</Step>

<Step>
### Configure the Root Route

Update your root route to use the Providers component:

```tsx title="app/routes/__root.tsx"
import { HeadContent, Outlet, Scripts, createRootRoute } from "@tanstack/react-router"
import type { ReactNode } from "react"

import { Header } from "@/components/header"
import globalsCss from "@/styles/globals.css?url"
import { Providers } from "../providers"

export const Route = createRootRoute({
    head: () => ({
        meta: [
            {
                charSet: "utf-8"
            },
            {
                name: "viewport",
                content: "width=device-width, initial-scale=1"
            },
            {
                title: "Better Auth TanStack Starter"
            }
        ],
        links: [
            { rel: "stylesheet", href: globalsCss },
            { rel: "icon", href: "/favicon.ico" },
            { rel: "apple-touch-icon", href: "/apple-touch-icon.png" },
            { rel: "manifest", href: "/manifest.webmanifest" }
        ]
    }),
    component: RootComponent
})

function RootComponent() {
    return (
        <RootDocument>
            <Outlet />
        </RootDocument>
    )
}

function RootDocument({ children }: Readonly<{ children: ReactNode }>) {
    return (
        <html lang="en" suppressHydrationWarning>
            <head>
                <meta
                    name="viewport"
                    content="initial-scale=1, viewport-fit=cover, width=device-width"
                />
                <meta
                    name="theme-color"
                    media="(prefers-color-scheme: light)"
                    content="oklch(1 0 0)"
                />
                <meta
                    name="theme-color"
                    media="(prefers-color-scheme: dark)"
                    content="oklch(0.145 0 0)"
                />

                <HeadContent />
            </head>

            <body>
                <Providers>
                    {children}
                </Providers>

                <Scripts />
            </body>
        </html>
    )
}
```
</Step>
</Steps>

## Setting Up Routes

TanStack Start uses a file-based routing system. Here's how to set up your authentication, account, and organization routes using the new v3 containers.

<Steps>
<Step>
### Auth Pages

Create the following route for authentication views:

```tsx title="app/routes/auth/$authView.tsx"
import { cn } from "@/lib/utils"
import { AuthView } from "@daveyplate/better-auth-ui"
import { createFileRoute } from "@tanstack/react-router"

export const Route = createFileRoute("/auth/$authView")({
    component: RouteComponent
})

function RouteComponent() {
    const { authView } = Route.useParams()

    return (
        <main className="container mx-auto flex grow flex-col items-center justify-center gap-3 self-center p-4 md:p-6">
            <AuthView pathname={authView} />

            <p className={cn(["callback", "sign-out"].includes(authView) && "hidden", "text-muted-foreground text-xs")}>
                Powered by{" "}
                <a className="text-warning underline" href="https://better-auth.com" target="_blank" rel="noreferrer">
                    better-auth.
                </a>
            </p>
        </main>
    )
}
```

This dynamic route covers all authentication paths, such as `sign-in`, `sign-up`, `magic-link`, `forgot-password`, `two-factor`, `recover-account`, `reset-password`, `sign-out`, and the internal `callback`.
</Step>

<Step>
### Account Pages

Create a dynamic route for account settings using the `AccountView` container (defaults to the `/account` base path):

```tsx title="app/routes/account/$accountView.tsx"
import { AccountView } from "@daveyplate/better-auth-ui"
import { createFileRoute } from "@tanstack/react-router"

export const Route = createFileRoute("/account/$accountView")({
    component: RouteComponent
})

function RouteComponent() {
    const { accountView } = Route.useParams()
    return (
        <main className="container mx-auto p-4 md:p-6">
            <AccountView pathname={accountView} />
        </main>
    )
}
```

You can customize the base path via the provider using `account={{ basePath: "/account" }}` if needed.
</Step>

<Step>
### Organization Pages

Create a dynamic route for organization settings using the `OrganizationView` container (defaults to the `/organization` base path):

```tsx title="app/routes/organization/$organizationView.tsx"
import { OrganizationView } from "@daveyplate/better-auth-ui"
import { createFileRoute } from "@tanstack/react-router"

export const Route = createFileRoute("/organization/$organizationView")({
    component: RouteComponent
})

function RouteComponent() {
    const { organizationView } = Route.useParams()
    return (
        <main className="container mx-auto p-4 md:p-6">
            <OrganizationView pathname={organizationView} />
        </main>
    )
}
```

If you prefer slug-based org URLs, set `organization={{ pathMode: "slug", basePath: "/organization", slug: currentSlug }}` in the provider and structure your routes accordingly:

```tsx title="app/routes/organization/$slug/$organizationView.tsx"
import { OrganizationView } from "@daveyplate/better-auth-ui"
import { createFileRoute } from "@tanstack/react-router"

export const Route = createFileRoute("/organization/$slug/$organizationView")({
    component: RouteComponent
})

function RouteComponent() {
    const { organizationView } = Route.useParams()
    return (
        <main className="container mx-auto p-4 md:p-6">
            <OrganizationView pathname={organizationView} />
        </main>
    )
}
```
</Step>
</Steps>

This setup provides a solid foundation for integrating Better Auth UI v3 with TanStack Start. You'll get all the benefits of TanStack's powerful routing system along with Better Auth UI's new container-based authentication and settings experiences.